home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume11 / sparc-mtools / part02 < prev    next >
Encoding:
Text File  |  1990-03-25  |  48.2 KB  |  1,971 lines

  1. Newsgroups: comp.sources.misc
  2. keywords: DOS, floppy
  3. subject: v11i082: Fast mtools,  + mkdfs for SparcStation1 or Sun-3/80 Part 2
  4. from: viktor@melon.princeton.edu (Viktor Dukhovni)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 11, Issue 82
  8. Submitted-by: viktor@melon.princeton.edu (Viktor Dukhovni)
  9. Archive-name: sparc-mtools/part02
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 2 (of 3)."
  18. # Contents:  Readme init.c mdir.c mkdfs.c mmd.c mrd.c mread.c mren.c
  19. #   mtype.c subdir.c
  20. # Wrapped by viktor@cucumber on Fri Mar 16 20:50:08 1990
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'Readme' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'Readme'\"
  24. else
  25. echo shar: Extracting \"'Readme'\" \(3809 characters\)
  26. sed "s/^X//" >'Readme' <<'END_OF_FILE'
  27. X                MTOOLS
  28. X            version 1.6.2 - 5 Jul 89
  29. X
  30. XThis is a collection of MSDOS tools to allow you to read and write to
  31. XMSDOS formatted diskettes from a Unix based system.
  32. X
  33. XThe following MSDOS commands are emulated:
  34. X
  35. XMtool         MSDOS
  36. Xname        equivalent    Description
  37. X-----        ----        -----------
  38. Xmcopy        COPY        copy MSDOS files to/from Unix
  39. Xmdel        DEL/ERASE    delete a MSDOS file
  40. Xmdir        DIR        display a MSDOS directory
  41. Xmkdfs        FORMAT        Format and build s DOS file system.
  42. Xmmd        MD/MKDIR    make a MSDOS sub directory
  43. Xmrd        RD/RMDIR    remove a MSDOS sub directory
  44. Xmread        COPY        low level read (copy) a MSDOS file to Unix
  45. Xmren        REN/RENAME    rename an existing MSDOS file
  46. Xmtype        TYPE        display contents of a MSDOS file
  47. Xmwrite        COPY        low level write (copy) a Unix file to MSDOS
  48. X*        CD        change working directory
  49. X
  50. X    * by use of the environmental variable MCWD
  51. X
  52. XThe formats of IBM PC floppy disk drives are:
  53. X
  54. X   bytes per  sectors per  tracks    number    total     disk   introduced
  55. X    sector      track     per side  of sides  capacity   size    in MSDOS
  56. X     512         8          40        1        160k      5.25      1.0
  57. X     512         9          40        1        180k      5.25      1.1
  58. X     512         8          40        2        320k      5.25      2.0
  59. X     512         9          40        2        360k      5.25      2.0
  60. X     512        15          80        2        1.2M      5.25      3.0
  61. X     512         9          80        2        720k      3.5       3.1
  62. X     512        18          80        2        1.4M      3.5       3.2
  63. X
  64. X
  65. XFind UNIX device(s) capable of reading one or more of these formats
  66. Xand edit "devices.c" to add them to the driver switch,  you may
  67. Xadd the same device more than once if it supports multiple formats
  68. Xand needs "ioctls" to be set to the right physical parameters.
  69. X
  70. XThe disk geometry can be kept in the environment for unusual cases,
  71. Xinit.c will pass "NCYL", "NSECT" and "NTRACK" to the disk parameter
  72. Xsetting routine (if any).  This should be documented in an "mtools"
  73. Xmanual page giving an overview of the whole package,  this file is a 
  74. Xstart.
  75. X
  76. XThe manuals are very terse...  it's assumed that the reader is already
  77. Xfamiliar with MSDOS.
  78. X
  79. XThe use of the environmental variable MCWD to keep track of the current
  80. Xworking directory is a little awkward, especially since there is no
  81. X'change directory' command.  Bourne shell users will have to type two
  82. Xcommands to initially set their working directory, ie:
  83. X
  84. X    MCWD=/TMP
  85. X    export MCWD
  86. X
  87. XWildcards are only applied to filenames and not to directory names.  For
  88. Xexample '/usr/local/*.c' is appropriate, but '/usr/l*/main.c' is not.
  89. X
  90. XI really wanted to avoid the use of a 'text' mode and a 'data' mode when
  91. Xtransferring files, but I couldn't find a better way.  It gets rather
  92. Xconfusing and it's quite possible to mess up a file if you apply the
  93. Xtext mode when it is not appropriate (ie:  to a COM or EXE file).
  94. XLikewise, if you forget to apply the text mode (to a Unix text file)
  95. Xthen if the file is used under MSDOS, it will be missing carriage
  96. Xreturns.  However, if you aren't going to use the files on your Unix
  97. Xsystem (you just intend to hold the files and then transfer them back to
  98. XMSDOS later) then you shouldn't use the text mode during either mread or
  99. Xmwrite.  This is because, the text mode is only useful if the files are
  100. Xgonna be used under Unix.
  101. X
  102. XThe implementation of the Mcopy command is somewhat clumbsy since the
  103. XMSDOS drive designation "A:" is used.  Mcopy is really a front-end to
  104. Xthe low level Mread and Mwrite commands.
  105. X
  106. XThere are is a shell archives called "Unixpc.shar" that contain files
  107. Xspecific to the AT&T Unix PC 7300/3b1.
  108. X
  109. XEmmet P. Gray                US Army, HQ III Corps & Fort Hood
  110. X...!uunet!uiucuxc!fthood!egray        Attn: AFZF-DE-ENV
  111. X                    Directorate of Engineering & Housing
  112. X                    Environmental Management Office
  113. X                    Fort Hood, TX 76544-5057
  114. END_OF_FILE
  115. if test 3809 -ne `wc -c <'Readme'`; then
  116.     echo shar: \"'Readme'\" unpacked with wrong size!
  117. fi
  118. # end of 'Readme'
  119. fi
  120. if test -f 'init.c' -a "${1}" != "-c" ; then 
  121.   echo shar: Will not clobber existing file \"'init.c'\"
  122. else
  123. echo shar: Extracting \"'init.c'\" \(5152 characters\)
  124. sed "s/^X//" >'init.c' <<'END_OF_FILE'
  125. X/*
  126. X * Initialize a MSDOS diskette.  Read the boot block for disk layout
  127. X * and switch to the proper floppy disk device to match the format
  128. X * of the disk.  Sets a bunch of global variables.  Returns 0 on success,
  129. X * or 1 on failure.
  130. X */
  131. X
  132. X#include <stdio.h>
  133. X#include <ctype.h>
  134. X#include <signal.h>
  135. X#include "devices.h"
  136. X#include "msdos.h"
  137. X
  138. X/* #undef DUP_FAT */
  139. X
  140. Xextern int fd, dir_len, dir_start, clus_size, fat_len, num_clus;
  141. Xextern unsigned char *fatbuf;
  142. Xextern char *mcwd;
  143. X
  144. X/* The available drivers */
  145. Xextern struct device fd_devices[];
  146. X
  147. X/* The bootblock */
  148. Xunion bootblock bb ;
  149. X
  150. Xint
  151. Xinit(mode)
  152. Xint mode;
  153. X{
  154. X  int code, buflen, intr();
  155. X  void perror(), exit(), move(), reset_dir();
  156. X  char *getenv(), *fixmcwd(), *malloc(), *dummy;
  157. X  long lseek();
  158. X  struct device *try;
  159. X  int ncyl = 0, nsect = 0, ntrack =0 ;
  160. X  char *floppy = getenv("FLOPPY");
  161. X
  162. X  /*
  163. X   * Let the user set the geometry in the environment
  164. X   * It is possible for this to be the only way out of the catch-22
  165. X   * wherein the geometry needs to be read from the first block
  166. X   * which cannot be read until the geometry is set!
  167. X   */
  168. X
  169. X  if ( dummy = getenv("NCYL") )
  170. X    ncyl = strtol(dummy,0,0) ;
  171. X  if ( dummy = getenv("NTRACK") )
  172. X    ntrack = strtol(dummy,0,0) ;
  173. X  if ( dummy = getenv("NSECT") )
  174. X    nsect = strtol(dummy,0,0) ;
  175. X  
  176. X  fd = -1 ;
  177. X
  178. X  for ( try = fd_devices ; try->drv_dev ; ++try )
  179. X    if ( !floppy ||
  180. X     strncmp(try->drv_dev, floppy, strlen(floppy)) == 0 ) {
  181. X      (void) fprintf(stderr,"\nTrying %s ... ",try->drv_dev) ;
  182. X      fflush(stderr);
  183. X      if ( (fd = open(try->drv_dev, mode|try->drv_mode)) > 0 ) {
  184. X    if ( try->drv_ifunc && (*(try->drv_ifunc))(fd,ncyl,ntrack,nsect) ) {
  185. X      close(fd) ;
  186. X      fd = -1;
  187. X      continue ;
  188. X    }
  189. X    if( read_boot() ) {
  190. X      close(fd) ;
  191. X      fd = -1;
  192. X      continue ;
  193. X    }
  194. X    (void) fprintf(stderr,"ok\n") ;
  195. X    fflush(stderr) ;
  196. X    break ;
  197. X      }
  198. X      perror("open") ;
  199. X    }
  200. X
  201. X  if ( fd < 0 ) {
  202. X    (void) fprintf(stderr,"All known devices failed.\nSorry.\n") ;
  203. X    exit(1) ;
  204. X  }
  205. X    
  206. X  dir_start = DIROFF(bb.sb) ;
  207. X  dir_len = DIRLEN(bb.sb);
  208. X  clus_size = CLSIZ(bb.sb);
  209. X  fat_len = FATLEN(bb.sb);
  210. X  num_clus = NCLUST(bb.sb);
  211. X
  212. X  /* Set the parameters if needed */
  213. X  if ( try->drv_ifunc )
  214. X    if( (*(try->drv_ifunc))(fd,NCYL(bb.sb),NTRACK(bb.sb),NSECT(bb.sb)) )
  215. X      exit(1) ;
  216. X  
  217. X  buflen = fat_len * MSECSIZ;
  218. X  fatbuf = (unsigned char *) malloc((unsigned int) buflen);
  219. X
  220. X  /* read the FAT sectors */
  221. X  move(FATOFF(bb.sb));
  222. X  if (read(fd, fatbuf, buflen) != buflen) {
  223. X    (void) fprintf(stderr,"Could not read the FAT table\n");
  224. X    perror("init: read");
  225. X    exit(1) ;
  226. X  }
  227. X
  228. X  /* set dir_chain to root directory */
  229. X  reset_dir();
  230. X  /* get Current Working Directory */
  231. X  mcwd = fixmcwd(getenv("MCWD"));
  232. X  /* test it out.. */
  233. X  if (subdir("")) {
  234. X    (void) fprintf(stderr, "Environment variable MCWD needs updating\n");
  235. X    exit(1);
  236. X  }
  237. X  return(0);
  238. X}
  239. X
  240. X/*
  241. X * Set the logical sector.  Non brain-dead drivers don't move the
  242. X * head until we ask for data,  so computing relative seeks is overkill.
  243. X */
  244. X
  245. Xvoid
  246. Xmove(sector)
  247. Xint sector;
  248. X{
  249. X  long lseek();
  250. X  void exit(), perror();
  251. X
  252. X  if (lseek(fd, (long)sector*MSECSIZ, 0) < 0) {
  253. X    perror("move: lseek");
  254. X    exit(1);
  255. X  }
  256. X}
  257. X
  258. X/*
  259. X * Fix MCWD to be a proper directory name.  Always has a leading separator.
  260. X * Never has a trailing separator (unless it is the path itself).
  261. X */
  262. X
  263. Xchar *
  264. Xfixmcwd(dirname)
  265. Xchar *dirname;
  266. X{
  267. X  char *s, *ans, *malloc(), *strcpy(), *strcat();
  268. X
  269. X  if (dirname == NULL)
  270. X    return("/");
  271. X
  272. X  ans = malloc((unsigned int) strlen(dirname)+2);
  273. X  /* add a leading separator */
  274. X  if (*dirname != '/' && *dirname != '\\') {
  275. X    strcpy(ans, "/");
  276. X    strcat(ans, dirname);
  277. X  }
  278. X  else
  279. X    strcpy(ans, dirname);
  280. X  /* translate to upper case */
  281. X  for (s = ans; *s; ++s) {
  282. X    if (islower(*s))
  283. X      *s = toupper(*s);
  284. X  }
  285. X  /* if separator alone */
  286. X  if (strlen(ans) == 1)
  287. X    return(ans);
  288. X  /* zap the trailing separator */
  289. X  s--;
  290. X  if (*s == '/' || *s == '\\')
  291. X    *s = '\0';
  292. X  return(ans);
  293. X}
  294. X
  295. X/*
  296. X * Do a graceful exit if the program is interupted.  This will reduce
  297. X * (but not eliminate) the risk of generating a corrupted disk on
  298. X * a user abort.
  299. X */
  300. X
  301. Xint
  302. Xintr()
  303. X{
  304. X  void writefat();
  305. X
  306. X  writefat();
  307. X  close(fd);
  308. X  exit(1);
  309. X}
  310. X
  311. X/*
  312. X * Write the FAT table to the disk.  Up to now the FAT manipulation has
  313. X * been done in memory.  All errors are fatal.  (Might not be too smart
  314. X * to wait till the end of the program to write the table.  Oh well...)
  315. X */
  316. X
  317. Xvoid
  318. Xwritefat()
  319. X{
  320. X  int buflen;
  321. X  void move();
  322. X
  323. X  move(FATOFF(bb.sb)) ;
  324. X  buflen = fat_len * MSECSIZ;
  325. X  if (write(fd, (char *) fatbuf, buflen) != buflen) {
  326. X    perror("writefat: write");
  327. X    exit(1);
  328. X  }
  329. X#ifdef DUP_FAT
  330. X  /* the duplicate FAT table */
  331. X  if (write(fd, (char *) fatbuf, buflen) != buflen) {
  332. X    perror("writefat: write");
  333. X    exit(1);
  334. X  }
  335. X#endif                /* DUP_FAT */
  336. X  return;
  337. X}
  338. X
  339. Xread_boot()
  340. X{
  341. X  unsigned char buf[MSECSIZ];
  342. X  static unsigned char ans;
  343. X
  344. X  move(0) ;
  345. X    
  346. X  if (read(fd, &bb, MSECSIZ) != MSECSIZ ) {
  347. X    return(1) ;
  348. X  }
  349. X  
  350. X  /* Do not know how to deal with non 512 byte blocks! */
  351. X  if ( SECSIZ(bb.sb) != MSECSIZ ) {
  352. X    fprintf(stderr,"File system block size of %d bytes is not valid\n",
  353. X            SECSIZ(bb.sb));
  354. X    exit(1) ;
  355. X  }
  356. X
  357. X  return(0) ;
  358. X}
  359. END_OF_FILE
  360. if test 5152 -ne `wc -c <'init.c'`; then
  361.     echo shar: \"'init.c'\" unpacked with wrong size!
  362. fi
  363. # end of 'init.c'
  364. fi
  365. if test -f 'mdir.c' -a "${1}" != "-c" ; then 
  366.   echo shar: Will not clobber existing file \"'mdir.c'\"
  367. else
  368. echo shar: Extracting \"'mdir.c'\" \(4882 characters\)
  369. sed "s/^X//" >'mdir.c' <<'END_OF_FILE'
  370. X/*
  371. X * Display a MSDOS directory
  372. X *
  373. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  374. X * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  375. X *                     Directorate of Engineering & Housing
  376. X *                     Environmental Management Office
  377. X *                     Fort Hood, TX 76544-5057
  378. X */
  379. X
  380. X#include <stdio.h>
  381. X#include "msdos.h"
  382. X
  383. Xint fd;                /* the file descriptor for the floppy */
  384. Xint dir_start;            /* starting sector for directory */
  385. Xint dir_len;            /* length of directory (in sectors) */
  386. Xint dir_entries;        /* number of directory entries */
  387. Xint dir_chain[25];        /* chain of sectors in directory */
  388. Xint clus_size;            /* cluster size (in sectors) */
  389. Xint fat_len;            /* length of FAT table (in sectors) */
  390. Xint num_clus;            /* number of available clusters */
  391. Xunsigned char *fatbuf;        /* the File Allocation Table */
  392. Xchar *mcwd;            /* the current working directory */
  393. X
  394. Xmain(argc, argv)
  395. Xint argc;
  396. Xchar *argv[];
  397. X{
  398. X    int i, entry, files, blocks, fargn, wide, faked;
  399. X    long size;
  400. X    char name[9], ext[4], *date, *time, *convdate(), *convtime();
  401. X    char *strncpy(), newpath[MAX_PATH], *getname(), *getpath(), *pathname;
  402. X    char *newfile, *filename, *unixname(), volume[12], *sep;
  403. X    char *strcpy(), *strcat(), newname[MAX_PATH], *strncat();
  404. X    void exit(), reset_dir(), free();
  405. X    struct directory *dir, *search();
  406. X
  407. X    if (init(0)) {
  408. X        fprintf(stderr, "mdir: Cannot initialize diskette\n");
  409. X        exit(1);
  410. X    }
  411. X                    /* find the volume label */
  412. X    reset_dir();
  413. X    volume[0] = '\0';
  414. X    for (entry=0; entry<dir_entries; entry++) {
  415. X        dir = search(entry);
  416. X                    /* if empty */
  417. X        if (dir->name[0] == 0x0)
  418. X            break;
  419. X                    /* if not volume label */
  420. X        if (!(dir->attr & 0x08))
  421. X            continue;
  422. X
  423. X        strncpy(volume, (char *) dir->name, 8);
  424. X        volume[8] = '\0';
  425. X        strncat(volume, (char *) dir->ext, 3);
  426. X        volume[11] = '\0';
  427. X        break;
  428. X    }
  429. X    if (volume[0] == '\0')
  430. X        printf(" Volume in drive has no label\n");
  431. X    else
  432. X        printf(" Volume in drive is %s\n", volume);
  433. X    fargn = 1;
  434. X    wide = 0;
  435. X                    /* first argument number */
  436. X    if (argc > 1) {
  437. X        if (!strcmp(argv[1], "-w")) {
  438. X            wide = 1;
  439. X            fargn = 2;
  440. X        }
  441. X    }
  442. X                    /* fake an argument */
  443. X    faked = 0;
  444. X    if (argc == fargn) {
  445. X        faked++;
  446. X        argc++;
  447. X    }
  448. X    files = 0;
  449. X    for (i=fargn; i<argc; i++) {
  450. X        if (faked) {
  451. X            filename = getname(".");
  452. X            pathname = getpath(".");
  453. X        }
  454. X        else {
  455. X            filename = getname(argv[i]);
  456. X            pathname = getpath(argv[i]);
  457. X        }
  458. X                    /* move to first guess subdirectory */
  459. X                    /* required by isdir() */
  460. X        if (subdir(pathname)) {
  461. X            free(filename);
  462. X            free(pathname);
  463. X            continue;
  464. X        }
  465. X                    /* is filename really a subdirectory? */
  466. X        if (isdir(filename)) {
  467. X            strcpy(newpath, pathname);
  468. X            if (strcmp(pathname,"/") && strcmp(pathname, "\\")) {
  469. X                if (*pathname != '\0')
  470. X                    strcat(newpath, "/");
  471. X            }
  472. X            strcat(newpath, filename);
  473. X                    /* move to real subdirectory */
  474. X            if (subdir(newpath)) {
  475. X                free(filename);
  476. X                free(pathname);
  477. X                continue;
  478. X            }
  479. X            strcpy(newname, "*");
  480. X        }
  481. X        else {
  482. X            strcpy(newpath, pathname);
  483. X            strcpy(newname, filename);
  484. X        }
  485. X
  486. X        if (*filename == '\0')
  487. X            strcpy(newname, "*");
  488. X
  489. X        if (*newpath == '/' || *newpath == '\\')
  490. X            printf(" Directory for %s\n\n", newpath);
  491. X        else if (!strcmp(newpath, "."))
  492. X            printf(" Directory for %s\n\n", mcwd);
  493. X        else {
  494. X            if (strlen(mcwd) == 1 || !strlen(newpath))
  495. X                sep = "";
  496. X            else
  497. X                sep = "/";
  498. X            printf(" Directory for %s%s%s\n\n", mcwd, sep, newpath);
  499. X        }
  500. X        for (entry=0; entry<dir_entries; entry++) {
  501. X            dir = search(entry);
  502. X                    /* if empty */
  503. X            if (dir->name[0] == 0x0)
  504. X                break;
  505. X                    /* if erased */
  506. X            if (dir->name[0] == 0xe5)
  507. X                continue;
  508. X                    /* if a volume label */
  509. X            if (dir->attr & 0x08)
  510. X                continue;
  511. X
  512. X            strncpy(name, (char *) dir->name, 8);
  513. X            strncpy(ext, (char *) dir->ext, 3);
  514. X            name[8] = '\0';
  515. X            ext[3] = '\0';
  516. X
  517. X            newfile = unixname(name, ext);
  518. X            if (!match(newfile, newname)) {
  519. X                free(newfile);
  520. X                continue;
  521. X            }
  522. X            free(newfile);
  523. X
  524. X            files++;
  525. X            if (wide && files != 1) {
  526. X                if (!((files-1) % 5))
  527. X                    putchar('\n');
  528. X            }
  529. X            date = convdate(dir->date[1], dir->date[0]);
  530. X            time = convtime(dir->time[1], dir->time[0]);
  531. X            size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
  532. X                    /* is a subdirectory */
  533. X            if (dir->attr & 0x10) {
  534. X                if (wide)
  535. X                    printf("%-9.9s%-6.6s", name, ext);
  536. X                else
  537. X                    printf("%8s %3s  <DIR>     %s  %s\n", name, ext, date, time);
  538. X                continue;
  539. X            }
  540. X            if (wide)
  541. X                printf("%-9.9s%-6.6s", name, ext);
  542. X            else
  543. X                printf("%8s %3s %8d   %s  %s\n", name, ext, size, date, time);
  544. X        }
  545. X        if (argc > 2)
  546. X            putchar('\n');
  547. X
  548. X        free(filename);
  549. X        free(pathname);
  550. X    }
  551. X
  552. X    blocks = getfree() * MSECSIZ;
  553. X    if (!files)
  554. X        printf("File \"%s\" not found\n", newname);
  555. X    else
  556. X        printf("     %3d File(s)     %6ld bytes free\n", files, blocks);
  557. X    close(fd);
  558. X    exit(0);
  559. X}
  560. X
  561. X/*
  562. X * Get the amount of free space on the diskette
  563. X */
  564. X
  565. Xint
  566. Xgetfree()
  567. X{
  568. X    register int i, total;
  569. X
  570. X    total = 0;
  571. X    for (i=2; i<num_clus+2; i++) {
  572. X                    /* if getfat returns zero */
  573. X        if (!getfat(i))
  574. X            total += clus_size;
  575. X    }
  576. X    return(total);
  577. X}
  578. END_OF_FILE
  579. if test 4882 -ne `wc -c <'mdir.c'`; then
  580.     echo shar: \"'mdir.c'\" unpacked with wrong size!
  581. fi
  582. # end of 'mdir.c'
  583. fi
  584. if test -f 'mkdfs.c' -a "${1}" != "-c" ; then 
  585.   echo shar: Will not clobber existing file \"'mkdfs.c'\"
  586. else
  587. echo shar: Extracting \"'mkdfs.c'\" \(4022 characters\)
  588. sed "s/^X//" >'mkdfs.c' <<'END_OF_FILE'
  589. X#ifndef sun
  590. X    /*
  591. X         * FIX ME!
  592. X     * All we need is a convenient way for the user to choose the
  593. X         * DOS layout parameters for the FS,  and yet I did not want
  594. X         * to hard code tables for the various drives.
  595. X         * Something like a /etc/dosformat.dat file would be nice
  596. X     * the user can then use mkdfs <drivename>,  this involes
  597. X     * table parsing routines etc.,  not too hard,  just unpleasant.
  598. X     */
  599. X    main() {
  600. X        printf("Do not know how to format disks on your system\n";
  601. X        exit(1) ;
  602. X    }
  603. X#else
  604. X
  605. X#include <stdio.h>
  606. X#include <fcntl.h>
  607. X#include <errno.h>
  608. X#include <sys/wait.h>
  609. X#include <sys/file.h>
  610. X#include <assert.h>
  611. X#include "msdos.h"
  612. X#include "bootblk.h"
  613. X
  614. X#define VOLLBL 0x8
  615. X#define FAT720 0xf9
  616. X#define FAT1440 0xf0
  617. Xstatic char floppy[] = "/dev/rfd0c" ;
  618. Xstatic char disklabel[] = "ANYDSKLABEL" ;
  619. X
  620. Xvoid move(), Write(), usage(), formatit() ;
  621. X
  622. Xstatic char *progname, buf[MSECSIZ] ;
  623. X
  624. Xmain(argc,argv)
  625. X  char **argv;
  626. X{
  627. X  int c, fd, sec ;
  628. X  int fat_len = 3 ;
  629. X  int fat = FAT720 ;
  630. X  int dir_len = 7 ;
  631. X  int hdflag=0, fflag = 0 ;
  632. X
  633. X  progname = argv[0] ;
  634. X
  635. X  while( (c=getopt(argc,argv,"hf")) != EOF ) {
  636. X    switch(c) {
  637. X    case 'f' :
  638. X      fflag++ ;
  639. X      break;
  640. X    case 'h' :
  641. X      hdflag++ ;
  642. X      break;
  643. X    case '?':
  644. X    default:
  645. X      fprintf(stderr,"Unknown option \"%c\"\n",c) ;
  646. X      usage() ;
  647. X    }
  648. X  }
  649. X
  650. X  if (fflag) 
  651. X    formatit(hdflag) ;
  652. X
  653. X  /*  Lets initialize the MSDOS FS */
  654. X
  655. X  if ( (fd=open(floppy,O_RDWR)) == -1 ) {
  656. X    fprintf(stderr,"%s: open: ",progname) ;
  657. X    perror(floppy) ;
  658. X    exit(1) ;
  659. X  }
  660. X
  661. X  if ( hdflag ) {
  662. X    dir_len=14 ;
  663. X    fat_len=9 ;
  664. X    fat=FAT1440 ;
  665. X  }
  666. X  
  667. X  bzero(buf,sizeof(buf)) ;
  668. X  bcopy(hdflag?hdboot:ldboot,buf,MSECSIZ) ;   /* Create the boot block */
  669. X  Write(fd,buf,MSECSIZ) ;   /* Dump the boot block */
  670. X  bzero(buf,sizeof(buf)) ;
  671. X  for( c=0; c < 2 ; ++c ) {
  672. X    buf[0] = fat ;
  673. X    buf[1] = 0xff ;
  674. X    buf[2] = 0xff ;
  675. X    Write(fd,buf,MSECSIZ) ;    /* First block of FAT */
  676. X    bzero(buf,3) ;
  677. X    for( sec=fat_len; --sec ; )
  678. X      Write(fd,buf,MSECSIZ) ;  /* Rest of FAT */
  679. X  }
  680. X  strcpy(((struct directory *)buf)->name,disklabel) ;
  681. X  ((struct directory *)buf)->attr= VOLLBL ;
  682. X  Write(fd,buf,MSECSIZ) ;  /* Root dir */
  683. X  bzero(buf,strlen(disklabel)) ;
  684. X  ((struct directory *)buf)->attr= 0 ;
  685. X  for( ; --dir_len ; )
  686. X    Write(fd,buf,MSECSIZ) ;  /* Root dir */
  687. X}
  688. X
  689. Xvoid 
  690. Xmove(fd,sector)
  691. X  int fd, sector ;
  692. X{
  693. X  if ( lseek(fd,sector*MSECSIZ,L_SET) != sector*MSECSIZ) {
  694. X    fprintf(stderr,"%s: lseek: ",progname) ;
  695. X    perror(floppy) ;
  696. X    exit(1) ;
  697. X  }
  698. X}
  699. X
  700. Xvoid
  701. XWrite(fd,buf,count)
  702. X  int fd,count ;
  703. X  char * buf ;
  704. X{
  705. X  if ( write(fd,buf,count) != count ) {
  706. X    fprintf(stderr,"%s: write: ",progname) ;
  707. X    perror(floppy) ;
  708. X    exit(1) ;
  709. X  }
  710. X}
  711. X
  712. Xvoid
  713. Xusage() 
  714. X{
  715. X  fprintf(stderr,"Usage: %s [-h] [-f]\n",progname) ;
  716. X  fprintf(stderr,"\tBuilds an empty DOS filesystem\n") ;
  717. X  fprintf(stderr,"\t-h: high density\n\t-f: reformat first\n") ;
  718. X  exit(1) ;
  719. X}
  720. X
  721. Xvoid
  722. Xformatit(hdq)
  723. X  int hdq;
  724. X{
  725. X  int pid;
  726. X  struct wait w;
  727. X  int retval;
  728. X
  729. X  if( (pid=fork()) == -1 ) {
  730. X    fprintf(stderr,"%s: ",progname) ;
  731. X    perror("fork") ;
  732. X    exit(1) ;
  733. X  }
  734. X
  735. X  if ( !pid ) {
  736. X    if ( hdq ) 
  737. X      execl("/bin/fdformat","fdformat",floppy,0) ;
  738. X    else
  739. X      execl("/bin/fdformat","fdformat","-l",floppy,0) ;
  740. X
  741. X    fprintf(stderr,"%s: ",progname) ;
  742. X    perror("exec") ;
  743. X    exit(1) ;
  744. X  }
  745. X
  746. X  while ( (retval=wait4(pid,&w,0,0)) == -1 && errno == EINTR ) ;
  747. X
  748. X  if (retval == -1) {
  749. X    fprintf(stderr,"%s: ",progname) ;
  750. X    perror("wait4") ;
  751. X    fprintf(stderr,"The format operation may have failed\nTry again\n") ;
  752. X    exit(1) ;
  753. X  }
  754. X
  755. X  if ( WIFSIGNALED(w) ) {
  756. X    fprintf(stderr,"%s: ",progname) ;
  757. X    psignal(w.w_termsig,"/bin/fdformat") ;
  758. X    if (w.w_coredump)
  759. X      fprintf(stderr,"Core dumped\n") ;
  760. X    exit(1) ;
  761. X  }
  762. X
  763. X  assert( WIFEXITED(w) ) ; /* If not signalled,  must be exited
  764. X                              we are not tracing stopped processes */
  765. X
  766. X  if ( w.w_retcode ) {
  767. X    fprintf(stderr,"%s: /bin/fdformat exited with non-zero exit code %d\n",
  768. X      progname,w.w_retcode) ;
  769. X    exit(1) ;
  770. X  }
  771. X}
  772. X#endif
  773. END_OF_FILE
  774. if test 4022 -ne `wc -c <'mkdfs.c'`; then
  775.     echo shar: \"'mkdfs.c'\" unpacked with wrong size!
  776. fi
  777. # end of 'mkdfs.c'
  778. fi
  779. if test -f 'mmd.c' -a "${1}" != "-c" ; then 
  780.   echo shar: Will not clobber existing file \"'mmd.c'\"
  781. else
  782. echo shar: Extracting \"'mmd.c'\" \(4058 characters\)
  783. sed "s/^X//" >'mmd.c' <<'END_OF_FILE'
  784. X/*
  785. X * Make a MSDOS sub directory
  786. X *
  787. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  788. X * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  789. X *                     Directorate of Engineering & Housing
  790. X *                     Environmental Management Office
  791. X *                     Fort Hood, TX 76544-5057
  792. X */
  793. X
  794. X#include <stdio.h>
  795. X#include "msdos.h"
  796. X
  797. Xint fd;                /* the file descriptor for the floppy */
  798. Xint dir_start;            /* starting sector for directory */
  799. Xint dir_len;            /* length of directory (in sectors) */
  800. Xint dir_entries;        /* number of directory entries */
  801. Xint dir_chain[25];        /* chain of sectors in directory */
  802. Xint clus_size;            /* cluster size (in sectors) */
  803. Xint fat_len;            /* length of FAT table (in sectors) */
  804. Xint num_clus;            /* number of available clusters */
  805. Xunsigned char *fatbuf;        /* the File Allocation Table */
  806. Xchar *mcwd;            /* the Current Working Directory */
  807. X
  808. Xmain(argc, argv)
  809. Xint argc;
  810. Xchar *argv[];
  811. X{
  812. X    int entry, slot, fat, dot, fargn, verbose;
  813. X    char *filename, *newfile, *fixname(), *strncpy();
  814. X    char *getpath(), *pathname, tname[9], text[4], *fixed, *unixname();
  815. X    void exit(), putcluster(), writefat(), writedir(), free();
  816. X    struct directory *dir, *search(), *mk_entry();
  817. X    long time(), now;
  818. X
  819. X    if (init(2)) {
  820. X        fprintf(stderr, "mmd: Cannot initialize diskette\n");
  821. X        exit(1);
  822. X    }
  823. X
  824. X    fargn = 1;
  825. X    verbose = 0;
  826. X    if (argc > 1) {
  827. X        if (!strcmp(argv[1], "-v")) {
  828. X            fargn = 2;
  829. X            verbose = 1;
  830. X        }
  831. X    }
  832. X                    /* only 1 directory ! */
  833. X    if (argc != fargn+1) {
  834. X        fprintf(stderr, "Usage: mmd [-v] msdosdirectory\n");
  835. X        exit(1);
  836. X    }
  837. X    fixed = fixname(argv[fargn], verbose);
  838. X
  839. X    strncpy(tname, fixed, 8);
  840. X    strncpy(text, fixed+8, 3);
  841. X    tname[8] = '\0';
  842. X    text[3] = '\0';
  843. X
  844. X    filename = unixname(tname, text);
  845. X    pathname = getpath(argv[fargn]);
  846. X
  847. X    if (subdir(pathname))
  848. X        exit(1);
  849. X                    /* see if exists and get slot */
  850. X    slot = -1;
  851. X    dot = 0;
  852. X    for (entry=0; entry<dir_entries; entry++) {
  853. X        dir = search(entry);
  854. X                    /* if empty */
  855. X        if (dir->name[0] == 0x0) {
  856. X            if (slot < 0)
  857. X                slot = entry;
  858. X            break;
  859. X        }
  860. X                    /* if erased */
  861. X        if (dir->name[0] == 0xe5) {
  862. X            if (slot < 0)
  863. X                slot = entry;
  864. X            continue;
  865. X        }
  866. X                    /* if not a directory */
  867. X        if (!(dir->attr & 0x10))
  868. X            continue;
  869. X
  870. X        strncpy(tname, (char *) dir->name, 8);
  871. X        strncpy(text, (char *) dir->ext, 3);
  872. X        tname[8] = '\0';
  873. X        text[3] = '\0';
  874. X
  875. X        newfile = unixname(tname, text);
  876. X                    /* save the 'dot' directory info */
  877. X        if (!strcmp(".", newfile))
  878. X            dot = dir->start[1]*0x100 + dir->start[0];
  879. X
  880. X        if (!strcmp(filename, newfile)) {
  881. X            fprintf(stderr, "mmd: Directory \"%s\" already exists\n", filename);
  882. X            exit(1);
  883. X        }
  884. X        free(newfile);
  885. X    }
  886. X                    /* no '.' entry means root directory */
  887. X    if (dot == 0 && slot < 0) {
  888. X        fprintf(stderr, "mmd: No directory slots\n");
  889. X        exit(1);
  890. X    }
  891. X                    /* make the directory grow */
  892. X    if (dot && slot < 0) {
  893. X        if (grow(dot)) {
  894. X            fprintf(stderr, "mmd: Disk full\n");
  895. X            exit(1);
  896. X        }
  897. X                    /* first slot in 'new' directory */
  898. X        slot = entry;
  899. X    }
  900. X    if ((fat = nextfat(0)) == -1) {
  901. X        fprintf(stderr, "mmd: Disk full\n");
  902. X        exit(1);
  903. X    }
  904. X                    /* make directory entry */
  905. X    time(&now);
  906. X    dir = mk_entry(fixed, 0x10, fat, 0L, now);
  907. X    writedir(slot, dir);
  908. X                    /* write the cluster */
  909. X    putfat(fat, 0xfff);
  910. X    putcluster(fat, dot);
  911. X                    /* write FAT sectors */
  912. X    writefat();
  913. X    close(fd);
  914. X    exit(0);
  915. X}
  916. X
  917. X/*
  918. X * Write a blank directory 'template' to the cluster starting at 'dot'.
  919. X */
  920. X
  921. Xvoid
  922. Xputcluster(dot, dot_dot)
  923. Xint dot, dot_dot;
  924. X{
  925. X    int buflen, start;
  926. X    static struct directory dirs[32];
  927. X    struct directory *mk_entry();
  928. X    void exit(), perror(), move();
  929. X    long time(), now;
  930. X
  931. X    start = (dot - 2)*clus_size + dir_start + dir_len;
  932. X    move(start);
  933. X
  934. X    buflen = clus_size * MSECSIZ;
  935. X                    /* make the '.' and '..' entries */    
  936. X    time(&now);
  937. X    dirs[0] = *mk_entry(".          ", 0x10, dot, 0L, now);
  938. X    dirs[1] = *mk_entry("..         ", 0x10, dot_dot, 0L, now);
  939. X
  940. X    if (write(fd, (char *) &dirs[0], buflen) != buflen) {
  941. X        perror("putcluster: write");
  942. X        exit(1);
  943. X    }
  944. X    return;
  945. X}
  946. X
  947. X/*
  948. X * Returns next free cluster or -1 if none are available.
  949. X */
  950. X
  951. Xint
  952. Xnextfat(last)
  953. Xint last;
  954. X{
  955. X    register int i;
  956. X
  957. X    for (i=last+1; i<num_clus+2; i++) {
  958. X        if (!getfat(i))
  959. X            return(i);
  960. X    }
  961. X    return(-1);
  962. X}
  963. END_OF_FILE
  964. if test 4058 -ne `wc -c <'mmd.c'`; then
  965.     echo shar: \"'mmd.c'\" unpacked with wrong size!
  966. fi
  967. # end of 'mmd.c'
  968. fi
  969. if test -f 'mrd.c' -a "${1}" != "-c" ; then 
  970.   echo shar: Will not clobber existing file \"'mrd.c'\"
  971. else
  972. echo shar: Extracting \"'mrd.c'\" \(3277 characters\)
  973. sed "s/^X//" >'mrd.c' <<'END_OF_FILE'
  974. X/*
  975. X * Delete a MSDOS sub directory
  976. X *
  977. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  978. X * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  979. X *                     Directorate of Engineering & Housing
  980. X *                     Environmental Management Office
  981. X *                     Fort Hood, TX 76544-5057
  982. X */
  983. X
  984. X#include <stdio.h>
  985. X#include "msdos.h"
  986. X
  987. Xint fd;                /* the file descriptor for the floppy */
  988. Xint dir_start;            /* starting sector for directory */
  989. Xint dir_len;            /* length of directory (in sectors) */
  990. Xint dir_entries;        /* number of directory entries */
  991. Xint dir_chain[25];        /* chain of sectors in directory */
  992. Xint clus_size;            /* cluster size (in sectors) */
  993. Xint fat_len;            /* length of FAT table (in sectors) */
  994. Xint num_clus;            /* number of available clusters */
  995. Xunsigned char *fatbuf;        /* the File Allocation Table */
  996. Xchar *mcwd;            /* the Current Working Directory */
  997. X
  998. Xmain(argc, argv)
  999. Xint argc;
  1000. Xchar *argv[];
  1001. X{
  1002. X    int ismatch, entry, start;
  1003. X    char *filename, *newfile, text[4], tname[9], *getname();
  1004. X    char *strncpy(), *pathname, *getpath(), *unixname();
  1005. X    void exit(), zapit(), writefat(), writedir(), free();
  1006. X    struct directory *dir, *search();
  1007. X
  1008. X    if (init(2)) {
  1009. X        fprintf(stderr, "mrd: Cannot initialize diskette\n");
  1010. X        exit(1);
  1011. X    }
  1012. X                    /* only 1 directory ! */
  1013. X    if (argc != 2) {
  1014. X        fprintf(stderr, "Usage: mrd mdsosdirectory\n");
  1015. X        exit(1);
  1016. X    }
  1017. X
  1018. X    filename = getname(argv[1]);
  1019. X    pathname = getpath(argv[1]);
  1020. X    if (subdir(pathname))
  1021. X        exit(1);
  1022. X
  1023. X    ismatch = 0;
  1024. X    for (entry=0; entry<dir_entries; entry++) {
  1025. X        dir = search(entry);
  1026. X                    /* if empty */
  1027. X        if (dir->name[0] == 0x0)
  1028. X            break;
  1029. X                    /* if erased */
  1030. X        if (dir->name[0] == 0xe5)
  1031. X            continue;
  1032. X                    /* if not dir */
  1033. X        if (!(dir->attr & 0x10))
  1034. X            continue;
  1035. X
  1036. X        strncpy(tname, (char *) dir->name, 8);
  1037. X        strncpy(text, (char *) dir->ext, 3);
  1038. X        tname[8] = '\0';
  1039. X        text[3] = '\0';
  1040. X
  1041. X        newfile = unixname(tname, text);
  1042. X        if (!strcmp(newfile, filename)) {
  1043. X            start = dir->start[1]*0x100 + dir->start[0];
  1044. X            if (!isempty(start)) {
  1045. X                fprintf(stderr, "mrd: Directory \"%s\" is not empty\n", filename);
  1046. X                exit(1);
  1047. X            }
  1048. X            if (!start) {
  1049. X                fprintf(stderr, "mrd: Can't remove root directory\n");
  1050. X                exit(1);
  1051. X            }
  1052. X            zapit(start);
  1053. X            dir->name[0] = 0xe5;
  1054. X            writedir(entry, dir);
  1055. X            ismatch = 1;
  1056. X        }
  1057. X        free(newfile);
  1058. X    }
  1059. X    if (!ismatch) {
  1060. X        fprintf(stderr, "mrd: Directory \"%s\" not found\n", filename);
  1061. X        exit(1);
  1062. X    }
  1063. X                    /* update the FAT sectors */
  1064. X    writefat();
  1065. X    close(fd);
  1066. X    exit(0);
  1067. X}
  1068. X
  1069. X/*
  1070. X * See if directory is empty.  Returns 1 if empty, 0 if not.  Can't use
  1071. X * subdir() and search() as it would clobber the globals.
  1072. X */
  1073. X
  1074. Xint
  1075. Xisempty(fat)
  1076. Xint fat;
  1077. X{
  1078. X    register int i;
  1079. X    int next, buflen, sector;
  1080. X    unsigned char tbuf[CLSTRBUF];
  1081. X    void perror(), exit(), move();
  1082. X
  1083. X    while (1) {
  1084. X        sector = (fat-2)*clus_size + dir_start + dir_len;
  1085. X        move(sector);
  1086. X        buflen = clus_size * MSECSIZ;
  1087. X        if (read(fd, (char *) tbuf, buflen) != buflen) {
  1088. X            perror("isempty: read");
  1089. X            exit(1);
  1090. X        }
  1091. X                    /* check first character of name */
  1092. X        for (i=0; i<MSECSIZ; i+=MDIRSIZ) {
  1093. X            if (tbuf[i] == '.')
  1094. X                continue;
  1095. X            if (tbuf[i] != 0x0 && tbuf[i] != 0xe5)
  1096. X                return(0);
  1097. X        }
  1098. X                    /* get next cluster number */
  1099. X        next = getfat(fat);
  1100. X        if (next == -1) {
  1101. X            fprintf(stderr, "isempty: FAT problem\n");
  1102. X            exit(1);
  1103. X        }
  1104. X                    /* end of cluster chain */
  1105. X        if (next >= 0xff8)
  1106. X            break;
  1107. X        fat = next;
  1108. X    }
  1109. X    return(1);
  1110. X}
  1111. END_OF_FILE
  1112. if test 3277 -ne `wc -c <'mrd.c'`; then
  1113.     echo shar: \"'mrd.c'\" unpacked with wrong size!
  1114. fi
  1115. # end of 'mrd.c'
  1116. fi
  1117. if test -f 'mread.c' -a "${1}" != "-c" ; then 
  1118.   echo shar: Will not clobber existing file \"'mread.c'\"
  1119. else
  1120. echo shar: Extracting \"'mread.c'\" \(6791 characters\)
  1121. sed "s/^X//" >'mread.c' <<'END_OF_FILE'
  1122. X/*
  1123. X * Read (copy) a MSDOS file to Unix
  1124. X *
  1125. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  1126. X * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  1127. X *                     Directorate of Engineering & Housing
  1128. X *                     Environmental Management Office
  1129. X *                     Fort Hood, TX 76544-5057
  1130. X */
  1131. X
  1132. X#include <stdio.h>
  1133. X#include <ctype.h>
  1134. X#include <sys/types.h>
  1135. X#include <sys/stat.h>
  1136. X#include "msdos.h"
  1137. X
  1138. X#define LOWERCASE
  1139. X
  1140. Xint fd;                /* the file descriptor for the floppy */
  1141. Xint dir_start;            /* starting sector for directory */
  1142. Xint dir_len;            /* length of directory (in sectors) */
  1143. Xint dir_entries;        /* number of directory entries */
  1144. Xint dir_chain[25];        /* chain of sectors in directory */
  1145. Xint clus_size;            /* cluster size (in sectors) */
  1146. Xint fat_len;            /* length of FAT table (in sectors) */
  1147. Xint num_clus;            /* number of available clusters */
  1148. Xunsigned char *fatbuf;        /* the File Allocation Table */
  1149. Xchar *buf;            /* The input buffer */
  1150. Xlong bufsiz;            /* It's size */
  1151. Xint maxcontig;            /* In clusters */
  1152. Xchar *mcwd;            /* the Current Working Directory */
  1153. X
  1154. Xextern union bootblock bb;
  1155. Xlong size;
  1156. Xlong current;
  1157. Xint textmode = 0;
  1158. Xint nowarn = 0;
  1159. X
  1160. Xmain(argc, argv)
  1161. Xint argc;
  1162. Xchar *argv[];
  1163. X{
  1164. X    extern int optind;
  1165. X    extern char *optarg;
  1166. X    int fat, i, ismatch, entry, single, c, oops, mod_time;
  1167. X    long mod_date, convstamp();
  1168. X    char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
  1169. X    char *strncpy(), *pathname, *getpath(), *target, tmp[MAX_PATH];
  1170. X    char *strcat(), *strcpy();
  1171. X    void perror(), exit(), free();
  1172. X    struct directory *dir, *search();
  1173. X    struct stat stbuf;
  1174. X
  1175. X    if (init(0)) {
  1176. X        fprintf(stderr, "mread: Cannot initialize diskette\n");
  1177. X        exit(1);
  1178. X    }
  1179. X                    /* get command line options */
  1180. X    oops = 0;
  1181. X    mod_time = 0;
  1182. X    while ((c = getopt(argc, argv, "tnm")) != EOF) {
  1183. X        switch(c) {
  1184. X            case 't':
  1185. X                textmode = 1;
  1186. X                break;
  1187. X            case 'n':
  1188. X                nowarn = 1;
  1189. X                break;
  1190. X            case 'm':
  1191. X                mod_time = 1;
  1192. X                break;
  1193. X            default:
  1194. X                oops = 1;
  1195. X                break;
  1196. X        }
  1197. X    }
  1198. X
  1199. X    if (oops || (argc - optind) < 2) {
  1200. X        fprintf(stderr, "Usage: mread [-tn] msdosfile unixfile\n");
  1201. X        fprintf(stderr, "    or mread [-tn] msdosfile [msdosfiles...] unixdirectory\n");
  1202. X        exit(1);
  1203. X    }
  1204. X                    /* only 1 file to copy... */
  1205. X    single = 1;
  1206. X    target = argv[argc-1];
  1207. X                    /* ...unless last arg is a directory */
  1208. X    if (!stat(target, &stbuf)) {
  1209. X        if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
  1210. X            single = 0;    
  1211. X    }
  1212. X                    /* too many arguments */
  1213. X    if (single && (argc - optind) != 2) {
  1214. X        fprintf(stderr,
  1215. X            "mread: too many arguments or target dir omitted\n");
  1216. X        exit(1);
  1217. X    }
  1218. X
  1219. X    bufsiz = NSECT(bb.sb) * NTRACK(bb.sb) ;
  1220. X    maxcontig = (bufsiz += clus_size - (--bufsiz) % clus_size)/clus_size;
  1221. X
  1222. X    if ( (buf = (char *)malloc(bufsiz *= MSECSIZ)) == NULL ) {
  1223. X        fprintf(stderr,"Could not allocate input buffer\n");
  1224. X        exit(1) ;
  1225. X    }
  1226. X
  1227. X    for (i=optind; i<argc-1; i++) {
  1228. X        filename = getname(argv[i]);
  1229. X        pathname = getpath(argv[i]);
  1230. X        if (subdir(pathname)) {
  1231. X            free(filename);
  1232. X            free(pathname);
  1233. X            continue;
  1234. X        }
  1235. X
  1236. X        ismatch = 0;
  1237. X        for (entry=0; entry<dir_entries; entry++) {
  1238. X            dir = search(entry);
  1239. X                    /* if empty */
  1240. X            if (dir->name[0] == 0x0)
  1241. X                break;
  1242. X                    /* if erased */
  1243. X            if (dir->name[0] == 0xe5)
  1244. X                continue;
  1245. X                    /* if dir or volume lable */
  1246. X            if ((dir->attr & 0x10) || (dir->attr & 0x08))
  1247. X                continue;
  1248. X
  1249. X            strncpy(tname, (char *) dir->name, 8);
  1250. X            strncpy(text, (char *) dir->ext, 3);
  1251. X            tname[8] = '\0';
  1252. X            text[3] = '\0';
  1253. X
  1254. X            newfile = unixname(tname, text);
  1255. X            fat = dir->start[1]*0x100 + dir->start[0];
  1256. X            size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
  1257. X            if (mod_time)
  1258. X                mod_date = convstamp(dir->time, dir->date);
  1259. X            else
  1260. X                mod_date = 0L;
  1261. X
  1262. X                    /* if single file */
  1263. X            if (single) {
  1264. X                if (!strcmp(newfile, filename)) {
  1265. X                    readit(fat, target, mod_date);
  1266. X                    ismatch = 1;
  1267. X                    break;
  1268. X                }
  1269. X            }
  1270. X                    /* if multiple files */
  1271. X            else {
  1272. X                if (match(newfile, filename)) {
  1273. X                    printf("Copying %s\n", newfile);
  1274. X                    strcpy(tmp, target);
  1275. X                    strcat(tmp, "/");
  1276. X                    strcat(tmp, newfile);
  1277. X                    readit(fat, tmp, mod_date);
  1278. X                    ismatch = 1;
  1279. X                }
  1280. X            }
  1281. X            free(newfile);
  1282. X        }
  1283. X        if (!ismatch)
  1284. X            fprintf(stderr, "mread: File \"%s\" not found\n", filename);
  1285. X        free(filename);
  1286. X        free(pathname);
  1287. X    }
  1288. X    close(fd);
  1289. X    exit(0);
  1290. X}
  1291. X
  1292. X/*
  1293. X * Decode the FAT chain given the begining FAT entry, open the named Unix
  1294. X * file for write.
  1295. X */
  1296. X
  1297. Xstatic int readpos;
  1298. X
  1299. Xint
  1300. Xreadit(fat, target, mod_date)
  1301. Xint fat;
  1302. Xchar *target;
  1303. Xlong mod_date;
  1304. X{
  1305. X    void getclusters() ;
  1306. X    char ans[10];
  1307. X    void exit();
  1308. X    int curfat;
  1309. X    FILE *fp;
  1310. X    struct stat stbuf;
  1311. X    struct utimbuf {
  1312. X        time_t actime;
  1313. X        time_t modtime;
  1314. X    } utbuf;
  1315. X
  1316. X#ifdef LOWERCASE
  1317. X    char *c;
  1318. X    c = target;
  1319. X    while(*c) {
  1320. X        if (isupper(*c))
  1321. X            *c = tolower(*c);
  1322. X        c++;
  1323. X    }
  1324. X#endif /* LOWERCASE */
  1325. X
  1326. X    if (!nowarn) {
  1327. X        if (!access(target, 0)) {
  1328. X            while (1) {
  1329. X                printf("File \"%s\" exists, overwrite (y/n) ? ", target);
  1330. X                gets(ans);
  1331. X                if (ans[0] == 'n' || ans[0] == 'N')
  1332. X                    return;
  1333. X                if (ans[0] == 'y' || ans[0] == 'Y')
  1334. X                    break;
  1335. X            }
  1336. X                    /* sanity checking */
  1337. X            if (!stat(target, &stbuf)) {
  1338. X                if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  1339. X                    fprintf(stderr, "mread: \"%s\" is not a regular file\n", target);
  1340. X                    return;
  1341. X                }
  1342. X            }
  1343. X        }
  1344. X    }
  1345. X
  1346. X    if (!(fp = fopen(target, "w"))) {
  1347. X        fprintf(stderr, "mread: Can't open \"%s\" for write\n", target);
  1348. X        return;
  1349. X    }
  1350. X
  1351. X    current = 0L;
  1352. X    readpos = -1;
  1353. X    for(;;) {
  1354. X        /*
  1355. X         * Find chain of contiguous clusters
  1356. X         * curfat -> last in chain + 1
  1357. X         */
  1358. X        for(curfat=fat;
  1359. X            ++curfat < fat + maxcontig &&
  1360. X            getfat(curfat-1)==curfat;) ;
  1361. X
  1362. X        getclusters(fat, curfat, fp);
  1363. X                    /* get next cluster number */
  1364. X        fat = getfat(--curfat);
  1365. X        if (fat == -1) {
  1366. X            fprintf(stderr, "mread: FAT problem\n");
  1367. X            exit(1);
  1368. X        }
  1369. X                    /* end of cluster chain */
  1370. X        if (fat >= 0xff8)
  1371. X            break;
  1372. X    }
  1373. X    if (fclose(fp)) {
  1374. X        fprintf(stderr,"Error closing %s\n",target) ;
  1375. X        perror("close?") ;
  1376. X        exit(1) ;
  1377. X    }
  1378. X                    /* preserve mod times ? */
  1379. X    if (mod_date != 0L) {
  1380. X        utbuf.actime = mod_date;
  1381. X        utbuf.modtime = mod_date;
  1382. X        utime(target, &utbuf);
  1383. X    }
  1384. X    return;
  1385. X}
  1386. X
  1387. X/*
  1388. X * Read the named cluster, write to the Unix file descriptor.
  1389. X */
  1390. X
  1391. Xvoid
  1392. Xgetclusters(start, end, fp)
  1393. XFILE *fp;
  1394. X{
  1395. X    register int i;
  1396. X    int buflen, blk;
  1397. X    void exit(), perror(), move();
  1398. X
  1399. X    blk = (start - 2)*clus_size + dir_start + dir_len;
  1400. X    if (blk != readpos)
  1401. X        move(blk);
  1402. X
  1403. X    buflen = (end-start) * clus_size * MSECSIZ;
  1404. X
  1405. X    if (read(fd, (char *) buf, buflen) != buflen) {
  1406. X        perror("getcluster: read");
  1407. X        exit(1);
  1408. X    }
  1409. X    readpos = blk + (end-start)*clus_size;
  1410. X                    /* stop at size not EOF marker */
  1411. X    if (textmode) {
  1412. X        for (i=0; i<buflen; i++) {
  1413. X            current++;
  1414. X            if (current > size) 
  1415. X                break;
  1416. X            if ( buf[i] == '\r')
  1417. X                continue;
  1418. X            if ( current == size && buf[i] == 0x1a)
  1419. X                continue;
  1420. X            putc((char) buf[i], fp);
  1421. X        }
  1422. X    }
  1423. X    else {
  1424. X        buflen = (size > buflen) ? buflen : size;
  1425. X        if (fwrite(buf,buflen,1,fp)!=1) {
  1426. X            perror("getclusters: fwrite") ;
  1427. X            exit(1) ;
  1428. X        }
  1429. X        size -= buflen ;
  1430. X    }
  1431. X        
  1432. X    return;
  1433. X}
  1434. END_OF_FILE
  1435. if test 6791 -ne `wc -c <'mread.c'`; then
  1436.     echo shar: \"'mread.c'\" unpacked with wrong size!
  1437. fi
  1438. # end of 'mread.c'
  1439. fi
  1440. if test -f 'mren.c' -a "${1}" != "-c" ; then 
  1441.   echo shar: Will not clobber existing file \"'mren.c'\"
  1442. else
  1443. echo shar: Extracting \"'mren.c'\" \(3153 characters\)
  1444. sed "s/^X//" >'mren.c' <<'END_OF_FILE'
  1445. X/*
  1446. X * Rename an existing MSDOS file
  1447. X *
  1448. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  1449. X * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  1450. X *                     Directorate of Engineering & Housing
  1451. X *                     Environmental Management Office
  1452. X *                     Fort Hood, TX 76544-5057
  1453. X */
  1454. X
  1455. X#include <stdio.h>
  1456. X#include "msdos.h"
  1457. X
  1458. Xint fd;                /* the file descriptor for the floppy */
  1459. Xint dir_start;            /* starting sector for directory */
  1460. Xint dir_len;            /* length of directory (in sectors) */
  1461. Xint dir_entries;        /* number of directory entries */
  1462. Xint dir_chain[25];        /* chain of sectors in directory */
  1463. Xint clus_size;            /* cluster size (in sectors) */
  1464. Xint fat_len;            /* length of FAT table (in sectors) */
  1465. Xint num_clus;            /* number of available clusters */
  1466. Xunsigned char *fatbuf;        /* the File Allocation Table */
  1467. Xchar *mcwd;            /* the Current Working Directory */
  1468. X
  1469. Xmain(argc, argv)
  1470. Xint argc;
  1471. Xchar *argv[];
  1472. X{
  1473. X    int entry, ismatch, nogo, fargn, verbose, got_it;
  1474. X    char *filename, *newfile, *fixname(), *strncpy(), *unixname();
  1475. X    char *getpath(), *pathname, tname[9], text[4], *getname(), *target;
  1476. X    char *new, ans[10], *temp, *strcpy();
  1477. X    void exit(), writedir(), free();
  1478. X    struct directory *dir, *search();
  1479. X
  1480. X    if (init(2)) {
  1481. X        fprintf(stderr, "mren: Cannot initialize diskette\n");
  1482. X        exit(1);
  1483. X    }
  1484. X    fargn = 1;
  1485. X    verbose = 0;
  1486. X    if (argc > 1) {
  1487. X        if (!strcmp(argv[1], "-v")) {
  1488. X            fargn = 2;
  1489. X            verbose = 1;
  1490. X        }
  1491. X    }
  1492. X    if (argc != fargn+2) {
  1493. X        fprintf(stderr, "Usage: mren [-v] sourcefile targetfile\n");
  1494. X        exit(1);
  1495. X    }
  1496. X    filename = getname(argv[fargn]);
  1497. X    pathname = getpath(argv[fargn]);
  1498. X    if (subdir(pathname))
  1499. X        exit(1);
  1500. X
  1501. X    temp = getname(argv[fargn+1]);
  1502. X    target = fixname(argv[fargn+1], verbose);
  1503. X
  1504. X    strncpy(tname, target, 8);
  1505. X    strncpy(text, target+8, 3);
  1506. X    tname[8] = '\0';
  1507. X    text[3] = '\0';
  1508. X
  1509. X    new = unixname(tname, text);
  1510. X    nogo = 0;
  1511. X                    /* the name supplied may be altered */
  1512. X    if (strcmp(temp, new) && verbose) {
  1513. X        while (!nogo) {
  1514. X            printf("Do you accept \"%s\" as the new file name (y/n) ? ", new);
  1515. X            gets(ans);
  1516. X            if (ans[0] == 'y' || ans[0] == 'Y')
  1517. X                break;
  1518. X            if (ans[0] == 'n' || ans[0] == 'N')
  1519. X                nogo = 1;
  1520. X        }
  1521. X    }
  1522. X    if (nogo)
  1523. X        exit(0);
  1524. X                    /* see if exists and do it */
  1525. X    ismatch = 0;
  1526. X    for (entry=0; entry<dir_entries; entry++) {
  1527. X        dir = search(entry);
  1528. X                    /* if empty */
  1529. X        if (dir->name[0] == 0x0)
  1530. X            break;
  1531. X                    /* if erased */
  1532. X        if (dir->name[0] == 0xe5)
  1533. X            continue;
  1534. X                    /* if volume label */
  1535. X        if (dir->attr == 0x08)
  1536. X            continue;
  1537. X                    /* you may rename a directory */
  1538. X        strncpy(tname, (char *) dir->name, 8);
  1539. X        strncpy(text, (char *) dir->ext, 3);
  1540. X        tname[8] = '\0';
  1541. X        text[3] = '\0';
  1542. X
  1543. X        newfile = unixname(tname, text);
  1544. X
  1545. X                    /* if the new name already exists */
  1546. X        if (!strcmp(new, newfile)) {
  1547. X            fprintf(stderr, "mren: File \"%s\" already exists\n", new);
  1548. X            exit(1);
  1549. X        }
  1550. X                    /* if the old name exists */
  1551. X        if (!strcmp(filename, newfile)) {
  1552. X            ismatch = 1;
  1553. X            got_it = entry;
  1554. X        }
  1555. X        free(newfile);
  1556. X    }
  1557. X    if (!ismatch) {
  1558. X        fprintf(stderr, "mren: File \"%s\" not found\n", filename);
  1559. X        exit(1);
  1560. X    }
  1561. X                    /* so go ahead and do it */
  1562. X    dir = search(got_it);
  1563. X    strncpy((char *) dir->name, target, 8);
  1564. X    strncpy((char *) dir->ext, target+8, 3);
  1565. X    writedir(got_it, dir);
  1566. X
  1567. X    close(fd);
  1568. X    exit(0);
  1569. X}
  1570. END_OF_FILE
  1571. if test 3153 -ne `wc -c <'mren.c'`; then
  1572.     echo shar: \"'mren.c'\" unpacked with wrong size!
  1573. fi
  1574. # end of 'mren.c'
  1575. fi
  1576. if test -f 'mtype.c' -a "${1}" != "-c" ; then 
  1577.   echo shar: Will not clobber existing file \"'mtype.c'\"
  1578. else
  1579. echo shar: Extracting \"'mtype.c'\" \(3748 characters\)
  1580. sed "s/^X//" >'mtype.c' <<'END_OF_FILE'
  1581. X/*
  1582. X * Display contents of a MSDOS file
  1583. X *
  1584. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  1585. X * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  1586. X *                     Directorate of Engineering & Housing
  1587. X *                     Environmental Management Office
  1588. X *                     Fort Hood, TX 76544-5057
  1589. X */
  1590. X
  1591. X#include <stdio.h>
  1592. X#include "msdos.h"
  1593. X
  1594. Xint fd;                /* the file descriptor for the floppy */
  1595. Xint dir_start;            /* starting sector for directory */
  1596. Xint dir_len;            /* length of directory (in sectors) */
  1597. Xint dir_entries;        /* number of directory entries */
  1598. Xint dir_chain[25];        /* chain of sectors in directory */
  1599. Xint clus_size;            /* cluster size (in sectors) */
  1600. Xint fat_len;            /* length of FAT table (in sectors) */
  1601. Xint num_clus;            /* number of available clusters */
  1602. Xunsigned char *fatbuf;        /* the File Allocation Table */
  1603. Xchar *mcwd;            /* the Current Working Directory */
  1604. X
  1605. Xlong size;
  1606. Xlong current;
  1607. Xint stripmode = 0;
  1608. Xint textmode = 0;
  1609. X
  1610. Xmain(argc, argv)
  1611. Xint argc;
  1612. Xchar *argv[];
  1613. X{
  1614. X    extern int optind;
  1615. X    extern char *optarg;
  1616. X    int fat, i, ismatch, entry, c, oops;
  1617. X    char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
  1618. X    char *strncpy(), *pathname, *getpath();
  1619. X    void exit(), readit(), free();
  1620. X    struct directory *dir, *search();
  1621. X
  1622. X    if (init(0)) {
  1623. X        fprintf(stderr, "mtype: Cannot initialize diskette\n");
  1624. X        exit(1);
  1625. X    }
  1626. X                    /* get command line options */
  1627. X    oops = 0;
  1628. X    while ((c = getopt(argc, argv, "st")) != EOF) {
  1629. X        switch(c) {
  1630. X            case 's':
  1631. X                stripmode = 1;
  1632. X                break;
  1633. X            case 't':
  1634. X                textmode = 1;
  1635. X                break;
  1636. X            default:
  1637. X                oops = 1;
  1638. X                break;
  1639. X        }
  1640. X    }
  1641. X
  1642. X    if (oops || (argc - optind) < 1) {
  1643. X        fprintf(stderr, "Usage: mtype [-st] msdosfile [msdosfiles...]\n");
  1644. X        exit(1);
  1645. X    }
  1646. X
  1647. X    for (i=optind; i<argc; i++) {
  1648. X        filename = getname(argv[i]);
  1649. X        pathname = getpath(argv[i]);
  1650. X        if (subdir(pathname)) {
  1651. X            free(filename);
  1652. X            free(pathname);
  1653. X            continue;
  1654. X        }
  1655. X        ismatch = 0;
  1656. X        for (entry=0; entry<dir_entries; entry++) {
  1657. X            dir = search(entry);
  1658. X                    /* if empty */
  1659. X            if (dir->name[0] == 0x0)
  1660. X                break;
  1661. X                    /* if erased */
  1662. X            if (dir->name[0] == 0xe5)
  1663. X                continue;
  1664. X                    /* if dir or volume label */
  1665. X            if ((dir->attr & 0x10) || (dir->attr & 0x08))
  1666. X                continue;
  1667. X
  1668. X            strncpy(tname, (char *) dir->name, 8);
  1669. X            strncpy(text, (char *) dir->ext, 3);
  1670. X            tname[8] = '\0';
  1671. X            text[3] = '\0';
  1672. X
  1673. X            newfile = unixname(tname, text);
  1674. X                    /* see it if matches the pattern */
  1675. X            if (match(newfile, filename)) {
  1676. X                fat = dir->start[1]*0x100 + dir->start[0];
  1677. X                size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
  1678. X                readit(fat);
  1679. X                ismatch = 1;
  1680. X            }
  1681. X            free(newfile);
  1682. X        }
  1683. X        if (!ismatch)
  1684. X            fprintf(stderr, "mtype: File \"%s\" not found\n", filename);
  1685. X        free(filename);
  1686. X        free(pathname);
  1687. X    }
  1688. X    close(fd);
  1689. X    exit(0);
  1690. X}
  1691. X
  1692. X/*
  1693. X * Decode the FAT chain given the begining FAT entry.
  1694. X */
  1695. X
  1696. Xvoid
  1697. Xreadit(fat)
  1698. Xint fat;
  1699. X{
  1700. X    void getcluster();
  1701. X
  1702. X    current = 0L;
  1703. X    while (1) {
  1704. X        getcluster(fat);
  1705. X                    /* get next cluster number */
  1706. X        fat = getfat(fat);
  1707. X        if (fat == -1) {
  1708. X            fprintf(stderr, "mtype: FAT problem\n");
  1709. X            exit(1);
  1710. X        }
  1711. X                    /* end of cluster chain */
  1712. X        if (fat >= 0xff8)
  1713. X            break;
  1714. X    }
  1715. X    return;
  1716. X}
  1717. X
  1718. X/*
  1719. X * Read the named cluster, output to the stdout.
  1720. X */
  1721. X
  1722. Xvoid
  1723. Xgetcluster(num)
  1724. Xint num;
  1725. X{
  1726. X    register int i;
  1727. X    int buflen, start;
  1728. X    unsigned char buf[CLSTRBUF];
  1729. X    void exit(), perror(), move();
  1730. X
  1731. X    start = (num - 2)*clus_size + dir_start + dir_len;
  1732. X    move(start);
  1733. X
  1734. X    buflen = clus_size * MSECSIZ;
  1735. X    if (read(fd, (char *) buf, buflen) != buflen) {
  1736. X        perror("getcluster: read");
  1737. X        exit(1);
  1738. X    }
  1739. X                    /* stop at size not EOF marker */
  1740. X    for (i=0; i<buflen; i++) {
  1741. X        current++;
  1742. X        if (current > size) 
  1743. X            break;
  1744. X        if (textmode && buf[i] == '\r')
  1745. X            continue;
  1746. X        if (textmode && current == size && buf[i] == 0x1a)
  1747. X            continue;
  1748. X        if (stripmode)
  1749. X            putchar(buf[i] & 0x7f);
  1750. X        else
  1751. X            putchar(buf[i]);
  1752. X    }
  1753. X    return;
  1754. X}
  1755. END_OF_FILE
  1756. if test 3748 -ne `wc -c <'mtype.c'`; then
  1757.     echo shar: \"'mtype.c'\" unpacked with wrong size!
  1758. fi
  1759. # end of 'mtype.c'
  1760. fi
  1761. if test -f 'subdir.c' -a "${1}" != "-c" ; then 
  1762.   echo shar: Will not clobber existing file \"'subdir.c'\"
  1763. else
  1764. echo shar: Extracting \"'subdir.c'\" \(3775 characters\)
  1765. sed "s/^X//" >'subdir.c' <<'END_OF_FILE'
  1766. X/*
  1767. X * subdir(), getdir(), get_chain(), reset_dir()
  1768. X */
  1769. X
  1770. X#include <stdio.h>
  1771. X#include "msdos.h"
  1772. X
  1773. Xextern int dir_chain[25], dir_start, dir_len, dir_entries, clus_size;
  1774. Xextern char *mcwd;
  1775. Xstatic char lastpath[MAX_PATH];
  1776. X
  1777. X/*
  1778. X * Parse the path names of a sub directory.  Both '/' and '\' are
  1779. X * valid separators.  However, the use of '\' will force the operator
  1780. X * to use quotes in the command line to protect '\' from the shell.
  1781. X * Returns 1 on error.  Attempts to optimize by remembering the last
  1782. X * path it parsed
  1783. X */
  1784. X
  1785. Xint
  1786. Xsubdir(name)
  1787. Xchar *name;
  1788. X{
  1789. X    char *s, *tmp, tbuf[MAX_PATH], *path, *strcpy(), *strcat();
  1790. X    int code;
  1791. X    void reset_dir();
  1792. X                    /* if full pathname */
  1793. X    if (*name == '/' || *name == '\\')
  1794. X        strcpy(tbuf, name);
  1795. X                    /* if relative to MCWD */
  1796. X    else {
  1797. X        if (!strlen(name))
  1798. X            strcpy(tbuf, mcwd);
  1799. X        else {
  1800. X            strcpy(tbuf, mcwd);
  1801. X            strcat(tbuf, "/");
  1802. X            strcat(tbuf, name);
  1803. X        }
  1804. X    }
  1805. X                    /* if paths are same, do nothing */
  1806. X    if (!strcmp(tbuf, lastpath))
  1807. X        return(0);
  1808. X                    /* not recursive, start at root */
  1809. X    reset_dir();
  1810. X    strcpy(lastpath, tbuf);
  1811. X                    /* zap the leading separator */
  1812. X    tmp = tbuf;
  1813. X    if (*tmp == '\\' || *tmp == '/')
  1814. X        tmp++;
  1815. X    for (s = tmp; *s; ++s) {
  1816. X        if (*s == '\\' || *s == '/') {
  1817. X            path = tmp;
  1818. X            *s = '\0';
  1819. X            if (getdir(path))
  1820. X                return(1);
  1821. X            tmp = s+1;
  1822. X        }
  1823. X    }
  1824. X    code = getdir(tmp);
  1825. X    return(code);
  1826. X}
  1827. X
  1828. X/*
  1829. X * Find the directory and get the starting cluster.  A null directory
  1830. X * is ok.  Returns a 1 on error.
  1831. X */
  1832. X
  1833. Xint
  1834. Xgetdir(path)
  1835. Xchar *path;
  1836. X{
  1837. X    int entry, start;
  1838. X    char *newname, *unixname(), *strncpy(), name[9], ext[4];
  1839. X    struct directory *dir, *search();
  1840. X    void reset_dir(), free();
  1841. X                    /* nothing required */
  1842. X    if (*path == '\0')
  1843. X        return(0);
  1844. X
  1845. X    for (entry=0; entry<dir_entries; entry++) {
  1846. X        dir = search(entry);
  1847. X                    /* if empty */
  1848. X        if (dir->name[0] == 0x0)
  1849. X            break;
  1850. X                    /* if erased */
  1851. X        if (dir->name[0] == 0xe5)
  1852. X            continue;
  1853. X                    /* skip if not a directory */
  1854. X        if (!(dir->attr & 0x10))
  1855. X            continue;
  1856. X
  1857. X        strncpy(name, (char *) dir->name, 8);
  1858. X        strncpy(ext, (char *) dir->ext, 3);
  1859. X        name[8] = '\0';
  1860. X        ext[3] = '\0';
  1861. X
  1862. X        newname = unixname(name, ext);
  1863. X        if (!strcmp(newname, path)) {
  1864. X            start = dir->start[1]*0x100 + dir->start[0];
  1865. X                    /* if '..' pointing to root */
  1866. X            if (!start && !strcmp(path, "..")) {
  1867. X                reset_dir();
  1868. X                return(0);
  1869. X            }
  1870. X                    /* fill in the directory chain */
  1871. X            dir_entries = get_chain(start) * 16;
  1872. X            return(0);
  1873. X        }
  1874. X        free(newname);
  1875. X    }
  1876. X                    /* if '.' or '..', must be root */
  1877. X    if (!strcmp(path, ".") || !strcmp(path, "..")) {
  1878. X        reset_dir();
  1879. X        return(0);
  1880. X    }
  1881. X    fprintf(stderr, "Path component \"%s\" is not a directory\n", path);
  1882. X    return(1);
  1883. X}
  1884. X
  1885. X/*
  1886. X * Fill in the global variable dir_chain.  Argument is the starting
  1887. X * cluster number.  Info, in this variable is used by search() to 
  1888. X * scan a directory.  An arbitrary limit of 25 sectors is placed, this
  1889. X * equates to 400 entries.  Returns the number of sectors in the chain.
  1890. X */
  1891. X
  1892. Xint
  1893. Xget_chain(num)                /* fill the directory chain */
  1894. Xint num;
  1895. X{
  1896. X    int i, next;
  1897. X    void exit();
  1898. X
  1899. X    i = 0;
  1900. X    while (1) {
  1901. X        dir_chain[i] = (num - 2)*clus_size + dir_start + dir_len;
  1902. X                    /* sectors, not clusters! */
  1903. X        if (clus_size == 2) {
  1904. X            dir_chain[i+1] = dir_chain[i] + 1;
  1905. X            i++;
  1906. X        }
  1907. X        i++;
  1908. X        if (i >= 25) {
  1909. X            fprintf(stderr, "get_chain: directory too large\n");
  1910. X            exit(1);
  1911. X        }
  1912. X                    /* get next cluster number */
  1913. X        next = getfat(num);
  1914. X        if (next == -1) {
  1915. X            fprintf(stderr, "get_chain: FAT problem\n");
  1916. X            exit(1);
  1917. X        }
  1918. X                    /* end of cluster chain */
  1919. X        if (next >= 0xff8) {
  1920. X            break;
  1921. X        }
  1922. X        num = next;
  1923. X    }
  1924. X    return(i);
  1925. X}
  1926. X
  1927. X/* 
  1928. X * Reset the global variable dir_chain to the root directory.
  1929. X */
  1930. X
  1931. Xvoid
  1932. Xreset_dir()
  1933. X{
  1934. X    register int i;
  1935. X
  1936. X    for (i=0; i<dir_len; i++)
  1937. X        dir_chain[i] = dir_start + i;
  1938. X    dir_entries = dir_len * 16;
  1939. X                    /* disable subdir() optimization */
  1940. X    lastpath[0] = '\0';
  1941. X    return;
  1942. X}
  1943. END_OF_FILE
  1944. if test 3775 -ne `wc -c <'subdir.c'`; then
  1945.     echo shar: \"'subdir.c'\" unpacked with wrong size!
  1946. fi
  1947. # end of 'subdir.c'
  1948. fi
  1949. echo shar: End of archive 2 \(of 3\).
  1950. cp /dev/null ark2isdone
  1951. MISSING=""
  1952. for I in 1 2 3 ; do
  1953.     if test ! -f ark${I}isdone ; then
  1954.     MISSING="${MISSING} ${I}"
  1955.     fi
  1956. done
  1957. if test "${MISSING}" = "" ; then
  1958.     echo You have unpacked all 3 archives.
  1959.     rm -f ark[1-9]isdone
  1960. else
  1961.     echo You still need to unpack the following archives:
  1962.     echo "        " ${MISSING}
  1963. fi
  1964. ##  End of shell archive.
  1965. exit 0
  1966.     Viktor Dukhovni <viktor@math.princeton.edu>    : ARPA
  1967.         <...!uunet!princeton!math!viktor>    : UUCP
  1968.     Fine Hall, Washington Rd., Princeton, NJ 08544  : US-Post
  1969.         +1-(609)-258-5792             : VOICE
  1970.  
  1971.